from io import TextIOBase, BufferedIOBase
from typing import Any
from bcat.error import InvalidArgumentError
from bcat.process.process import Process
from bcat.stream.io_wrapper import BinaryReader, TextReader, BinaryWriter, TextWriter


class ProcessInfo(object):
    class Stream(object):
        def __init__(self, process: Process):
            self.__process = process
        def process(self) -> Process:
            return self.__process

        def check_binary_stream(self, name: str, stream: Any) -> None:
            if stream is None:
                raise InvalidArgumentError.no_args(f"{name} of process is None, stream:{stream}, process:{self.process()}")
            if not isinstance(stream, BufferedIOBase):
                raise InvalidArgumentError.no_args(f"Must not set text attribute before execution, stream:{stream}, process:{self.process()}")
        def check_text_stream(self, name: str, stream: Any) -> None:
            if stream is None:
                raise InvalidArgumentError.no_args(f"{name} of process is None, stream:{stream}, process:{self.process()}")
            if not isinstance(stream, TextIOBase):
                raise InvalidArgumentError.no_args(f"text attribute is not set before execution, stream:{stream}, process:{self.process()}")
            

    class Stdin(Stream):
        def __init__(self, process: Process):
            super().__init__(process)

        def binary_writer(self) -> BinaryWriter:
            stdin = self.process().stdin()
            self.check_binary_stream('stdin', stdin)
            return BinaryWriter(stdin)

        def text_writer(self) -> TextWriter:
            stdin = self.process().stdin()
            self.check_text_stream('stdin', stdin)
            return TextWriter(stdin)

    class Stdout(Stream):
        def __init__(self, process: Process):
            super().__init__(process)
        
        def binary_reader(self) -> BinaryReader:
            stdout = self.process().stdout()
            self.check_binary_stream('stdout', stdout)
            return BinaryReader(stdout)

        def text_reader(self) -> TextReader:
            stdout = self.process().stdout()
            self.check_text_stream('stdout', stdout)
            return TextReader(stdout)
    class Stderr(Stream):
        def __init__(self, process: Process):
            super().__init__(process)

        def binary_reader(self) -> BinaryReader:
            stderr = self.process().stderr()
            self.check_binary_stream('stderr', stderr)
            return BinaryReader(stderr)

        def text_reader(self) -> TextReader:
            stderr = self.process().stderr()
            self.check_text_stream('stderr', stderr)
            return TextReader(stderr)

#TODO: unittest

